import * as path from 'node:path';

import { Inject, Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as fse from 'fs-extra';

import { type IConfiguration } from '../../config/configuration';
import { type IScheDuleRule } from '../../interface.d';
import { fullScreenChrome } from '../../utils';
import { DataFactory } from '../common/global/dataFactory/dataFactory.service';

type IJson = {
  name: string;
  coverPngPath: string;
  tags: string[];
  topic: string;
  mp4Path: string;
  desc: string;
};

@Injectable()
export class BiliService {
  @Inject()
  private globalService: DataFactory;

  private readonly logger = new Logger(BiliService.name);

  @Inject(ConfigService)
  private configService: ConfigService<IConfiguration>;

  async run(rule: IScheDuleRule) {
    const { cacheDirName, jsonConfigPath } = rule;

    const browser = await this.globalService.createBroswer(cacheDirName);

    const [page] = await browser.pages();

    fullScreenChrome();

    await page.setRequestInterception(true);

    page.on('request', interceptedRequest => {
      if (interceptedRequest.isInterceptResolutionHandled()) return;

      const url = interceptedRequest.url();

      if (url.endsWith('.png') || url.endsWith('.jpg') || url.endsWith('output.mp4')) interceptedRequest.abort();
      else interceptedRequest.continue();
    });

    await page.goto('https://member.bilibili.com/', { waitUntil: 'networkidle0' });

    page.off('request');

    await page.setRequestInterception(false);

    const isLogin = page.url().includes('login');

    if (isLogin) {
      this.logger.error('未登录');

      await browser.close();
      return;
    }

    this.logger.verbose('已登录', '直接跳转到视频上传视频页面');

    await page.bringToFront();

    await page.goto('https://member.bilibili.com/platform/upload/video/frame', { waitUntil: 'networkidle0' });

    this.logger.verbose('等待上传逻辑');

    const {
      name,
      coverPngPath: _coverPngPath,
      mp4Path: _mp4Path,
      tags,
      desc,
    } = <IJson>fse.readJSONSync(jsonConfigPath);

    const desktopPath = this.globalService.getDesktopPath();

    const mp4Path = path.join(_mp4Path.replace(/^.+products/gi, desktopPath).replace(/(\\|\/)/gi, path.sep));

    const coverPngPath = path.join(_coverPngPath.replace(/^.+products/gi, desktopPath).replace(/(\\|\/)/gi, path.sep));

    this.logger.verbose('如果有未提交的视频则点击不用了');
    const giveupBtn = await page.$('.entrance-tip-btn::-p-text(不用了)');
    await giveupBtn?.click({ delay: 5000 });

    this.logger.verbose('上传视频');
    const uploadBtn = await page.waitForSelector('input[type=file][multiple=multiple]');
    await uploadBtn.uploadFile(mp4Path);

    this.logger.verbose('等待2s');
    await page.waitForFunction(() => new Promise(r => setTimeout(() => r(true), 2000)));

    this.logger.verbose('点击暂停上传');
    // await page.locator('.operate-btns .icon-btn').click({ delay: 100 });
    const stopAndPauseBtn = await page.$('.operate-btns .icon-btn');
    await stopAndPauseBtn?.click({ delay: 200 });

    this.logger.verbose('点击更改封面');
    await page
      .locator('.cover-upload-mask-btn span::-p-text(更改封面)')
      .setTimeout(60 * 1000)
      .click({ delay: 5000 });

    this.logger.verbose('点击上传封面');
    await page
      .locator('.cover-select-header-tab-item .text::-p-text(上传封面)')
      .setTimeout(60 * 1000)
      .click({ delay: 5000 });

    this.logger.verbose('上传封面');
    const coverImgUploadBtn = await page.waitForSelector('div::-p-text(拖拽图片到此或点击上传)', {
      timeout: 60 * 1000,
    });

    const [otherFileChooser] = await Promise.all([page.waitForFileChooser(), coverImgUploadBtn?.click()]);
    await otherFileChooser.accept([coverPngPath]);

    this.logger.verbose('点击完成');
    await page.locator('span::-p-text( 完成 )').click({ delay: 5000 });

    this.logger.verbose('输入标题');
    await page.type('.input-instance .input-val', name);

    this.logger.verbose('循环输入标签');
    const tagInput = await page.$('input[placeholder="按回车键Enter创建标签"]');

    for (const tagValue of tags) {
      await tagInput?.type(tagValue);

      await page.keyboard.press('Enter', { delay: 3000 });
    }

    this.logger.verbose('输入：视频描述内容');
    await page.evaluate(text => $('.ql-editor p').text(text), desc.trim());

    this.logger.verbose('点击开始上传');
    await stopAndPauseBtn?.click({ delay: 5000 });

    this.logger.verbose('等待上传完成');
    await page
      .locator('.success::-p-text(上传完成)')
      .setTimeout(15 * 60 * 1000)
      .wait();

    this.logger.verbose('点击立即投稿');
    await page.locator('.submit-add::-p-text(立即投稿)').click();

    await page.locator('::-p-text(稿件投递成功)').wait();
    this.logger.verbose('投递成功');

    await browser.close();
  }
}
